<template>
  <div class="question-mixed">
    <mu-tabs :value.sync="tabActive" center>
      <mu-tab>表单页</mu-tab>
      <mu-tab>轮询页</mu-tab>
    </mu-tabs>
    <div v-if="tabActive === 0">
      <mu-alert v-if="modified" color="orange">
        <mu-icon left value="priority_high"></mu-icon>
        <span>当前题目未保存，现在修改配置将会导致数据丢失</span>
      </mu-alert>
      <div class="question-mixed-config">
        <div class="form-item">
          <span class="form-title">题目类型：</span>
        </div>
        <type-select v-model="config.type_id" />
        <div class="form-item">
          <span class="form-title">题目形式：</span>
          <div class="form-input">
            <mu-radio v-model="config.style" class="form-radio-item" :value="0" label="选择题"></mu-radio>
            <mu-radio v-model="config.style" class="form-radio-item" :value="1" label="填空题"></mu-radio>
          </div>
        </div>
        <div class="form-item">
          <span class="form-title">有无图片：</span>
          <div class="form-input">
            <mu-radio v-model="config.has_image" class="form-radio-item" :value="true" label="有"></mu-radio>
            <mu-radio v-model="config.has_image" class="form-radio-item" :value="false" label="无"></mu-radio>
          </div>
        </div>
        <div v-if="config.style === 0" class="form-item">
          <span class="form-title">选项个数：</span>
          <div class="form-input">
            <mu-text-field v-model.number="config.option_count" full-width placeholder="输入数字，非选择题将忽略"></mu-text-field>
          </div>
        </div>

        <!-- 消息提示区 -->
        <div class="question-alert">
          <ul class="error-list mu-error-color">
            <li v-for="msg in configValid.errors" :key="msg" class="error-item">{{ msg }}</li>
          </ul>
          <ul class="warning-list">
            <li v-for="msg in configValid.warnings" :key="msg" class="warning-item">{{ msg }}</li>
          </ul>
        </div>

        <!-- 温馨提示 -->
        <div class="tips">
          <p class="mu-secondary-text">在这边选好题目类型、形式等信息，就可以点击“轮询页”开始出题了哦。</p>
          <p class="mu-secondary-text">离开出题前，表单页所有设置将一直有效，并且不会再次要求输入。</p>
        </div>
      </div>
    </div>
    <div v-else-if="tabActive === 1">
      <div class="question-mixed-poll">
        <p class="question-poll-question">{{ pollQuestion }}</p>
        <div v-if="currentStep === 'text'" class="question-input">
          <!-- 题干 -->
          <mu-text-field v-model="form.text" full-width placeholder="请在这里输入题干" multi-line :rows="1" :rows-max="3"></mu-text-field>
        </div>
        <div v-else-if="currentStep === 'image'" class="question-input">
          <!-- 图片 -->
          <image-input v-if="config.has_image" v-model="form.image" />
        </div>
        <div v-else-if="currentStep === 'options'" class="question-input">
          <!-- 选项 -->
          <options-input ref="optionsInput" v-model="form.options" />
        </div>
        <div v-else-if="currentStep === 'answer_text'" class="question-input">
          <!-- 填空题答案 -->
          <mu-text-field v-model="form.answer" full-width placeholder="请在这里输入答案" multi-line :rows="1" :rows-max="3"></mu-text-field>
        </div>
        <div v-else-if="currentStep === 'answer_option'" class="question-input">
          <!-- 选择题答案 -->
          <answer-select v-model="form.answer" :options="form.options" />
        </div>

        <!-- 消息提示区 -->
        <div class="question-alert">
          <ul class="error-list mu-error-color">
            <li v-for="msg in formValid.errors" :key="msg" class="error-item">{{ msg }}</li>
          </ul>
          <ul class="warning-list">
            <li v-for="msg in formValid.warnings" :key="msg" class="warning-item">{{ msg }}</li>
          </ul>
        </div>

        <!-- 步骤栏 -->
        <div class="question-actions">
          <mu-button v-if="canBack" class="question-actions-button" color="orange" @click="move(-1)">上一步</mu-button>
          <mu-button v-if="canForward" class="question-actions-button" color="success" @click="forward()">下一步</mu-button>
          <template v-if="canSubmit">
            <mu-button v-if="qcConfig.preview" class="question-actions-button" color="success" @click="preview()">预览</mu-button>
            <mu-button v-else class="question-actions-button" :color="submitButtonInfo.color" @click="submit()">{{ submitButtonInfo.text }}</mu-button>
          </template>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { mapGetters, mapMutations } from 'vuex'
import { QuestionValidate, Question } from '@/util/validate'
import { convertCreateQuestionStatusToButtonInfo } from '@/util'
import { submitQuestion } from '@/mixins'
import TypeSelect from '@/components/TypeSelect'
import OptionsInput from '@/components/OptionsInput'
import AnswerSelect from '@/components/AnswerSelect'
import ImageInput from '@/components/ImageInput'

export default {
  name: 'QuestionMixed',
  components: {
    TypeSelect,
    AnswerSelect,
    ImageInput,
    OptionsInput
  },
  mixins: [
    submitQuestion
  ],
  props: {
    modified: {
      type: Boolean,
      required: true
    }
  },
  data() {
    return {
      tabActive: 1,
      config: {
        type_id: 0,
        style: 0,
        has_image: true,
        option_count: 4
      },
      configValid: {
        errors: [],
        warnings: []
      },
      form: {
        text: '',
        image: null,
        options: [],
        answer: ''
      },
      formValid: {
        errors: [],
        warnings: []
      },
      status: {
        id: 0,
        submitting: false,
        question: false,
        image: false
      },
      currentStep: 'text',
      last: '',
      commit: 0
    }
  },
  computed: {
    ...mapGetters({
      qcConfig: 'questionCreateConfig'
    }),
    mergedForm() {
      return {
        type_id: this.config.type_id,
        style: this.config.style,
        text: this.form.text,
        image: this.config.has_image ? this.form.image : null,
        options: (this.config.style) === 0 ? this.form.options : [],
        answer: this.form.answer
      }
    },
    pollPath() {
      const { style, has_image } = this.config
      const path = ['text']
      if (has_image) {
        path.push('image')
      }
      if (style === 0) {
        path.push('options')
        path.push('answer_option')
      } else {
        path.push('answer_text')
      }
      return path
    },
    pollQuestion() {
      const map = {
        text: '这道题的题干是什么呢？',
        image: '这道题的图片是什么呢？',
        options: '选项分别是哪些呢？',
        answer_text: '答案是什么呢？',
        answer_option: '答案是哪一个呢？'
      }
      return map[this.currentStep] || ('系统错误，请联系管理员（' + this.currentStep + '）')
    },
    currentStepIndex() {
      return parseInt(this.pollPath.indexOf(this.currentStep))
    },
    canBack() {
      return this.currentStepIndex > 0
    },
    canForward() {
      return this.currentStepIndex < (this.pollPath.length - 1)
    },
    canSubmit() {
      return this.currentStepIndex === (this.pollPath.length - 1)
    },
    lastEqaulsForm() {
      return this.last !== JSON.stringify(this.form)
    },
    submitButtonInfo() {
      return convertCreateQuestionStatusToButtonInfo(this.status)
    },
    redirected() {
      return this.$route.params.redirected === true
    }
  },
  watch: {
    config: {
      deep: true,
      handler() {
        this.commit = 0
        if (this.checkConfigValid()) {
          this.updateQcConfig()
          // 不再清除表单，而是视情况回到第一步，数据保留
          if (this.currentStepIndex < 0) {
            this.currentStep = 'text'
          }
          if (this.config.option_count !== this.form.options.length) {
            this.form.options = Array(this.config.option_count).fill('')
          }
        }
      }
    },
    form: {
      deep: true,
      handler() {
        this.commit = 0
      }
    },
    lastEqaulsForm(val) {
      this.$emit('update:modified', val)
    }
  },
  created() {
    if (this.redirected) {
      this.tabActive = 1
    } else {
      this.tabActive = 0
    }
    this.loadQcConfig()
    this.checkConfigValid()
    this.clearForm()
    this.clearStatus()
  },
  methods: {
    ...mapMutations({
      setQcConfig: 'SET_QUESTION_CREATE_CONFIG',
      setQcForm: 'SET_QUESTION_CREATE_FORM'
    }),
    // 清空表单
    clearForm() {
      const n = this.config.option_count
      this.form.text = ''
      this.form.image = null
      this.form.options = Array(n).fill('')
      this.form.answer = ''
      this.last = JSON.stringify(this.form)
      this.currentStep = 'text'
    },
    // 清空状态
    clearStatus() {
      this.status = {
        id: 0,
        submitting: false,
        question: false,
        image: false
      }
    },
    // 从store读取config
    loadQcConfig() {
      this.config.type_id = this.qcConfig.type_id
      this.config.style = this.qcConfig.style
      this.config.has_image = this.qcConfig.has_image
      this.config.option_count = this.qcConfig.option_count
    },
    // 写入config
    updateQcConfig() {
      const config = { ...this.qcConfig }
      config.type_id = this.config.type_id
      config.style = this.config.style
      config.has_image = this.config.has_image
      config.option_count = parseInt(this.config.option_count) || 4
      this.setQcConfig(config)
    },
    // 刷新QcForm
    updateQcForm() {
      this.setQcForm(this.mergedForm)
    },
    // 检查配置合法性
    checkConfigValid() {
      const validate = new QuestionValidate(this.config)
      const { errors } = this.configValid = validate.checkType().checkStyle().checkOptionCount().get()
      return errors.length === 0
    },
    // 检查表单合法性
    checkFormValid() {
      var result = null
      switch (this.currentStep) {
        case 'text': result = Question.checkText(this.mergedForm); break
        case 'image': result = Question.checkImage(this.mergedForm, this.config.has_image); break
        case 'options': result = Question.checkOptions(this.mergedForm); break
        case 'answer_option':
        case 'answer_text':
          result = Question.isValid(this.mergedForm) // 最后一次直接检查整个题目
          break
      }
      if (result === null) {
        result = { errors: [], warnings: [] }
      }
      const { errors, warnings } = this.formValid = result
      if (errors.length > 0) {
        this.$toast.error('题目存在错误，不能提交')
      } else if (warnings.length > 0 && this.commit === 0) {
        this.$toast.warning('题目可能存在问题，仍要继续请再次点击“查看预览”')
      }
      const isValid = (errors.length === 0 && warnings.length === 0) || (errors.length === 0 && this.commit >= 1)
      // 记录尝试一次
      if (isValid) {
        this.commit = 0
      } else {
        this.commit++
      }
      return isValid
    },
    // 移动步骤
    move(diff) {
      const steps = this.pollPath
      const index = this.currentStepIndex
      const next = (index + steps.length + parseInt(diff)) % steps.length
      this.currentStep = steps[next]
    },
    // 下一步
    forward() {
      if (this.checkFormValid()) {
        this.move(1)
      }
    },
    // 预览
    preview() {
      if (this.checkFormValid()) {
        this.last = JSON.stringify(this.form)
        this.updateQcForm()
        this.$nextTick(() => {
          this.$router.push({ name: 'question-create-preview' })
        })
      }
    },
    // 提交题目
    async submit() {
      if (await this.submitQuestion()) {
        this.clearForm()
        this.clearStatus()
      }
    },
    // 覆盖submitQuestion
    submitQuestion() {
      return this._submitQuestion(this.mergedForm, this.status)
    }
  }
}
</script>

<style scoped>
.question-mixed-config {
  margin: 0 auto;
  width: 800px;
  padding: 12px;
}
.question-mixed-poll {
  margin: 0 auto;
  width: 500px;
  padding: 12px;
}

.form-item {
  display: flex;
  align-items: center;
}
.form-title {
  font-size: 1.2em;
}
.form-input {
  padding: 6px 0;
  display: flex;
  flex-flow: row nowrap;
  align-items: center;
}
.form-radio-item {
  margin: 8px;
}

.question-poll-question {
  padding: 1em;
  font-size: 2em;
  text-align: center;
}
.question-actions {
  text-align: center;
}
.question-actions-button {
  margin: 6px;
}

.question-alert {
  margin: 16px auto;
  width: 500px;
}
.error-list,
.warning-list {
  list-style: none;
  color: #fff;
}
.warning-list {
  background-color: #fb8c00;
}
.error-item,
.warning-item {
  padding: 6px 9px;
}

.is-phone .question-mixed-config {
  width: 100%;
}
.is-phone .question-mixed-poll {
  width: 100%;
}
</style>
